﻿using SEIPropertyDataService.Entity.Enums;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SEIPropertyDataService.Entity.ViewModels
{
    /// <summary>
    /// 键-名，供前端下拉框使用
    /// </summary>
    public class LabelValueModel
    {
        /// <summary>
        /// 键
        /// </summary>
        public string Value { get; set; }
        /// <summary>
        /// 名
        /// </summary>
        public string Label { get; set; }
        /// <summary>
        /// 子项列表
        /// </summary>
        public List<LabelValueModel> Childs { get; set; }
        /// <summary>
        /// 扩展属性，可以存储任意类型的数据
        /// </summary>
        public object Ext { get; set; } = null;
        /// <summary>
        /// 扩展属性1，可以存储任意类型的数据
        /// </summary>
        public object Ext1 { get; set; } = null;
        /// <summary>
        /// 
        /// </summary>
        public LabelValueModel()
        {

        }
        /// <summary>
        /// 构造函数，传入键和名称，如果名称为空，则使用键作为名称
        /// </summary>
        /// <param name="key"></param>
        /// <param name="name"></param>
        public LabelValueModel(string key, string name = null)
        {
            this.Value = key;
            if (name == null)
                this.Label = key;
            else
                this.Label = name;
        }
        /// <summary>
        /// 将字符串隐式转换为 LabelValueModel，键为字符串本身，名称为 null
        /// </summary>
        /// <param name="key"></param>
        public static implicit operator LabelValueModel(string key)
        {
            return new LabelValueModel(key);
        }
        /// <summary>
        /// 获取指定温度单位的最小值-纯组分
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        public static List<VM_InputLimitModel> GetMinValueOfTempertureOfPure(TempertureUnits temp)
        {
            List<VM_InputLimitModel> limits = new List<VM_InputLimitModel>();
            switch (temp)
            {
                case TempertureUnits.K:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "1",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        RangeTargetStart = 0.0d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "2",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterThan,
                        RangeTargetStart = 0.0d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "3",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        RangeTargetStart = 0.0d
                    });
                    break;
                case TempertureUnits.F:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "1",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterThan,
                        RangeTargetStart = -459.67d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "2",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterThan,
                        RangeTargetStart = -459.67d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "3",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterThan,
                        RangeTargetStart = -459.67d
                    });
                    break;
                case TempertureUnits.C:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "1",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        RangeTargetStart = -273.15d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "2",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterThan,
                        RangeTargetStart = -273.15d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "3",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        RangeTargetStart = -273.15d
                    });
                    break;
                case TempertureUnits.R:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "1",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        RangeTargetStart = 0.0d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "2",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterThan,
                        RangeTargetStart = 0.0d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "3",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        RangeTargetStart = 0.0d
                    });
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(temp), "未知的温度单位");
            }
            return limits;
        }
        /// <summary>
        /// 获取拟合回归纯组分温度的限制范围
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        private static List<VM_InputLimitModel> GetMinValueOfTempertureOfRegressionPure(TempertureUnits temp)
        {
            List<VM_InputLimitModel> limits = new List<VM_InputLimitModel>();
            switch (temp)
            {
                case TempertureUnits.K:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "STD-DEV",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = 0.0d,
                        RangeTargetEnd = 5000.0d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "DATA",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = 0.0d,
                        RangeTargetEnd = 5000.0d
                    });
                    break;
                case TempertureUnits.F:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "STD-DEV",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = 0.0d,
                        RangeTargetEnd = 8540.32d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "DATA",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = -459.669d,
                        RangeTargetEnd = 8540.32d
                    });
                    break;
                case TempertureUnits.C:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "STD-DEV",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = 0.0d,
                        RangeTargetEnd = 4726.85
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "DATA",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = -273.149d,
                        RangeTargetEnd = 4726.85
                    });
                    break;
                case TempertureUnits.R:
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "STD-DEV",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = 0.0d,
                        RangeTargetEnd = 8999.99d
                    });
                    limits.Add(new VM_InputLimitModel()
                    {
                        Vary = "DATA",
                        CompareTypeOfRangeStart = InputLimitCmpTypes.GreaterOrEqThan,
                        CompareTypeOfRangeEnd = InputLimitCmpTypes.LessOrEqThan,
                        RangeTargetStart = 0.0d,
                        RangeTargetEnd = 8999.99d
                    });
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(temp), "未知的温度单位");
            }
            return limits;
        }
        /// <summary>
        /// 将枚举转换为 List《KeyNameModel》，Key 为枚举值，Name 为枚举名称
        /// </summary>
        /// <typeparam name="TEnum">枚举类型</typeparam>
        /// <param name="ext"> 扩展属性，可以存储任意类型的数据</param>
        /// <param name="getDescFunc"> 获取枚举描述的函数，默认为 null</param>
        /// <param name="flag">标识位，1：纯组分温度；2：拟合回归纯组分温度</param>
        /// <returns>List《KeyNameModel》</returns>
        public static List<LabelValueModel> EnumToKeyNameModelList<TEnum>(object ext = null, Func<TEnum, string> getDescFunc = null, int? flag = null) where TEnum : Enum
        {
            if (typeof(TEnum) == typeof(TempertureUnits))
            {
                if (flag.HasValue && flag.Value == 1)
                {
                    return Enum.GetValues(typeof(TEnum))
                       .Cast<TEnum>()
                       .Select(e =>
                       {
                           string desc = getDescFunc?.Invoke(e);
                           return new LabelValueModel
                           {
                               Ext = ext, // 扩展属性
                               Ext1 = GetMinValueOfTempertureOfPure((TempertureUnits)Convert.ToInt32(e)),
                               Value = Convert.ToInt32(e).ToString(), // 枚举值作为 Key
                               Label = !string.IsNullOrWhiteSpace(desc) ? desc : e.ToString() // 优先用描述
                           };
                       }).OrderBy(x => x.Value == "4" ? 0 : 1).ToList();
                }
                else if (flag.HasValue && flag.Value == 2)
                {
                    return Enum.GetValues(typeof(TEnum))
                       .Cast<TEnum>()
                       .Select(e =>
                       {
                           string desc = getDescFunc?.Invoke(e);
                           return new LabelValueModel
                           {
                               Ext = ext, // 扩展属性
                               Ext1 = GetMinValueOfTempertureOfRegressionPure((TempertureUnits)Convert.ToInt32(e)),
                               Value = Convert.ToInt32(e).ToString(), // 枚举值作为 Key
                               Label = !string.IsNullOrWhiteSpace(desc) ? desc : e.ToString() // 优先用描述
                           };
                       }).OrderBy(x => x.Value == "4" ? 0 : 1).ToList();
                }
            }
            return Enum.GetValues(typeof(TEnum))
                       .Cast<TEnum>()
                       .Select(e =>
                       {
                           string desc = getDescFunc?.Invoke(e);
                           return new LabelValueModel
                           {
                               Ext = ext, // 扩展属性
                               Value = Convert.ToInt32(e).ToString(), // 枚举值作为 Key
                               Label = !string.IsNullOrWhiteSpace(desc) ? desc : e.ToString() // 优先用描述
                           };
                       })
                       .ToList();
        }
    }
}
